package java0.conc0303;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

/**
 * 本周作业：（必做）思考有多少种方式，在main函数启动一个新线程或线程池，
 * 异步运行一个方法，拿到这个方法的返回值后，退出主线程？
 * 写出你的方法，越多越好，提交到github。
 *
 * 一个简单的代码参考：
 */
public class Homework03 {
    
    public static void main(String[] args) throws Exception {
        
        long start=System.currentTimeMillis();

        // 在这里创建一个线程或线程池，
        // 异步执行 下面方法
        int result = sum(); //这是得到的返回值


        // 第1种方法
        int result1 = CompletableFuture.supplyAsync(() -> sum()).get();
        // 确保  拿到result 并输出
        System.out.println("第1种方法异步计算结果为："+result1);

        // 第2种方法
        FutureTask<Integer> task =  new FutureTask<>(() -> sum());
        new Thread(task).start();
        Integer result2 = task.get();
        System.out.println("第2种方法异步计算结果为："+result2);

        // 第3种方法
        ExecutorService executorService = Executors.newFixedThreadPool(1);
        executorService.submit(task);
        executorService.shutdown();
        Integer result3 = task.get();
        System.out.println("第3种方法异步计算结果为："+result3);
        // 第4种方法 使用forkjoin
        ExecutorService executorService1 = Executors.newWorkStealingPool();
        executorService1.submit(task);
        executorService1.shutdown();
        Integer result4 = task.get();
        System.out.println("第4种方法异步计算结果为："+result4);

        // 第5钟，自定义线程
        SumThread sumThread = new SumThread();
        sumThread.start();
        Integer result5 = sumThread.getResult();
        System.out.println("第5种方法异步计算结果为："+result5);

        System.out.println("使用时间："+ (System.currentTimeMillis()-start) + " ms");
        
        // 然后退出main线程
    }
    
    private static int sum() {
        return fibo(36);
    }
    
    private static int fibo(int a) {
        if ( a < 2) 
            return 1;
        return fibo(a-1) + fibo(a-2);
    }

    static class SumThread extends Thread {
        private Integer result;

        public Integer getResult() {
            return result;
        }

        @Override
        public  void run() {
            result = sum();
        }
    }
}
